﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NTQOnlineExam.Services.EntityFW.Context;
using NTQOnlineExam.Services.EntityFW.Entity;

namespace NTQOnlineExam.Services.EntityFW.Repository
{
    public class UnitOfWork : IUnitOfWork, IDisposable
    {
        private readonly ExamOnlineDbContext _context = new ExamOnlineDbContext();
        private Hashtable _repositories;
        private DbTransaction _transaction;
        private ObjectContext _objectContext;
        //private GenericRepository<Section> billRepository;

        //public IGenericRepository<Section> BillRepository()
        //{

        //  if (this.billRepository == null)
        //  {
        //    this.billRepository = new GenericRepository<Section>(_context);
        //  }
        //  return this.billRepository;

        //}

        public void Save()
        {

            _context.SaveChanges();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    _context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            if (_objectContext != null && _objectContext.Connection.State == ConnectionState.Open)
                _objectContext.Connection.Close();

            Dispose(true);
            GC.SuppressFinalize(this);
        }

        //public object GetRepository(Type type)
        //{
        //  if (type == typeof(Section)) return BillRepository();
        //  return null;
        //}

        //public IGenericRepository<Entity.Section> SectionRepository()
        //{
        //  throw new NotImplementedException();
        //}


        public IGenericRepository<T> Repository<T>() where T : class
        {
            if (_repositories == null)
                _repositories = new Hashtable();

            var type = typeof(T).Name;

            if (!_repositories.ContainsKey(type))
            {
                var repositoryType = typeof(GenericRepository<>);

                var repositoryInstance =
                    Activator.CreateInstance(repositoryType
                            .MakeGenericType(typeof(T)), _context);

                _repositories.Add(type, repositoryInstance);
            }

            return (IGenericRepository<T>)_repositories[type];
        }



        #region Unit of Work Transactions

        public void BeginTransaction()
        {
            _objectContext = ((IObjectContextAdapter)_context).ObjectContext;
            if (_objectContext.Connection.State != ConnectionState.Open)
            {
                _objectContext.Connection.Open();
                _transaction = _objectContext.Connection.BeginTransaction();
            }
        }

        public bool Commit()
        {
            _transaction.Commit();
            return true;
        }

        public void Rollback()
        {
            _transaction.Rollback();
           // ((DbContext)_context).SyncObjectsStatePostCommit();
        }

        #endregion
    }

}